home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Kant Generator Pro 1.2 / src / kode ƒ / kant parser.c < prev    next >
C/C++ Source or Header  |  1994-11-14  |  8KB  |  353 lines

  1. #include "kant parser.h"
  2. #include "text twiddling.h"
  3. #include "util.h"
  4. #include "program globals.h"
  5. #include "cancel.h"
  6. #include "environment.h"
  7. #include "window layer.h"
  8.  
  9. static    void SafeDisposeHandle(Handle theHandle);
  10. static    unsigned char GetTheCharacter(short *currentPosition);
  11. static    void RememberCharacter(unsigned char theChar);
  12. static    enum ErrorType GetReferenceName(Str255 theReferenceName, short *endPosition);
  13. static    enum ErrorType GetReferenceID(Str255 theReferenceName, short *refNum, short *numOptions);
  14. static    enum ErrorType InstantiateReference(Str255 theText, short refNum, short numOptions);
  15. static    enum ErrorType ReplaceTheText(short start, short end, Str255 theStr);
  16. static    enum ErrorType GetChoiceText(Str255 theText, short start, short *end, Boolean chooseFirst);
  17. static    enum ErrorType GetOptionalText(Str255 theText, short start, short *end, Boolean chooseFirst);
  18.  
  19. static    TEHandle        gTheTEHandle;
  20. static    WindowPtr        gTheWindow;
  21. static    short            gTheWindowIndex;
  22. static    short            gTheTEPosition;
  23. static    short            gTheEndPosition;
  24. static    short            gTheTELength;
  25. static    unsigned char    gRememberedChar;
  26. static    Boolean            gRememberedCharValid;
  27.  
  28. void InitTheParser(WindowPtr theWindow, short rawStart, short rawEnd)
  29. {
  30.     gTheTEHandle=GetWindowTE(theWindow);
  31.     gTheWindow=theWindow;
  32.     gTheWindowIndex=GetWindowIndex(theWindow);
  33.     gTheTEPosition=rawStart;
  34.     gTheEndPosition=rawEnd;
  35.     gTheTELength=(**gTheTEHandle).teLength;
  36.     gRememberedChar=0x00;
  37.     gRememberedCharValid=FALSE;
  38. }
  39.  
  40. enum ErrorType ParseLoop(void)
  41. {
  42.     unsigned char    theChar;
  43.     short            currentPosition, endPosition;
  44.     Str255            theReferenceName;
  45.     enum ErrorType    theError;
  46.     Str255            theText;
  47.     short            numOptions;
  48.     short            refNum;
  49.     
  50.     theChar=' ';
  51.     while (theChar!=0xFF)    /* end of text */
  52.     {
  53.         theChar=GetTheCharacter(¤tPosition);
  54.         switch (theChar)
  55.         {
  56.             case '&':    /* reference */
  57.                 theError=GetReferenceName(theReferenceName, &endPosition);
  58.                 if (theError!=kNoError)
  59.                     return theError;
  60.                 theError=GetReferenceID(theReferenceName, &refNum, &numOptions);
  61.                 if (theError!=kNoError)
  62.                     return theError;
  63.                 if (numOptions==0)
  64.                     return kNoInstantiations;
  65.                 theError=InstantiateReference(theText, refNum, numOptions);
  66.                 if (theError!=kNoError)
  67.                     return theError;
  68.                 theError=ReplaceTheText(currentPosition, endPosition, theText);
  69.                 if (theError!=kNoError)
  70.                     return theError;
  71.                 break;
  72.             case '[':    /* choice */
  73.                 theError=GetChoiceText(theText, currentPosition, &endPosition,
  74.                     (TickCount()%2) ? TRUE : FALSE);
  75.                 if (theError!=kNoError)
  76.                     return theError;
  77.                 theError=ReplaceTheText(currentPosition, endPosition, theText);
  78.                 if (theError!=kNoError)
  79.                     return theError;
  80.                 break;
  81.             case '<':    /* optional text */
  82.                 theError=GetOptionalText(theText, currentPosition, &endPosition,
  83.                     (TickCount()%2) ? TRUE : FALSE);
  84.                 if (theError!=kNoError)
  85.                     return theError;
  86.                 theError=ReplaceTheText(currentPosition, endPosition, theText);
  87.                 if (theError!=kNoError)
  88.                     return theError;
  89.                 break;
  90.             case '#':    /* next letter capitalized */
  91.                 theChar=GetTheCharacter(&endPosition);
  92.                 if (((theChar>='a') && (theChar<='z')) ||
  93.                     ((theChar>='A') && (theChar<='Z')))
  94.                 {
  95.                     theText[0]=0x01;
  96.                     theText[1]=theChar&0xdf;
  97.                     theError=ReplaceTheText(currentPosition, endPosition+1, theText);
  98.                     if (theError!=kNoError)
  99.                         return theError;
  100.                 }
  101.                 else RememberCharacter(theChar);
  102.                 break;
  103.             case '\\':    /* backslash character */
  104.                 theChar=GetTheCharacter(&endPosition);
  105.                 switch (theChar)
  106.                 {
  107.                     case 'r':
  108.                     case 'R':
  109.                         theText[0]=0x01;
  110.                         theText[1]='\r';
  111.                         break;
  112.                     case 't':
  113.                     case 'T':
  114.                         theText[0]=0x01;
  115.                         theText[1]='\t';
  116.                         break;
  117.                     case '0':
  118.                         theText[0]=0x00;
  119.                         break;
  120.                     default:
  121.                         return kBadBackslash;
  122.                         break;
  123.                 }
  124.                 theError=ReplaceTheText(currentPosition, endPosition+1, theText);
  125.                 if (theError!=kNoError)
  126.                     return theError;
  127.                 break;
  128.         }
  129.     }
  130.     
  131.     return kNoError;
  132. }
  133.  
  134. /* --------------------------------------------------------- */
  135. /* the rest of these functions are internal to kant parser.c */
  136. /* --------------------------------------------------------- */
  137.  
  138. static    void SafeDisposeHandle(Handle theHandle)
  139. {
  140.     if (theHandle!=0L)
  141.         DisposeHandle(theHandle);
  142. }
  143.  
  144. static    unsigned char GetTheCharacter(short *currentPosition)
  145. {
  146.     if (gRememberedCharValid)
  147.     {
  148.         gRememberedCharValid=FALSE;
  149.         *currentPosition=gTheTEPosition-1;
  150.         
  151.         return gRememberedChar;
  152.     }
  153.     else
  154.     {
  155.         *currentPosition=gTheTEPosition;
  156.         
  157.         if (gTheTEPosition<gTheTELength)
  158.         {
  159.             return (*(**gTheTEHandle).hText)[gTheTEPosition++];
  160.         }
  161.         else
  162.         {
  163.             return 0xFF;
  164.         }
  165.     }
  166. }
  167.  
  168. static    void RememberCharacter(unsigned char theChar)
  169. {
  170.     gRememberedChar=theChar;
  171.     gRememberedCharValid=TRUE;
  172. }
  173.  
  174. static    enum ErrorType GetReferenceName(Str255 theReferenceName, short *endPosition)
  175. {
  176.     unsigned char    theChar;
  177.     short            dummyPosition;
  178.     
  179.     theReferenceName[0]=0x00;
  180.     theChar=GetTheCharacter(&dummyPosition);
  181.     while ((theChar!=0xFF) &&
  182.             (((theChar>='a') && (theChar<='z')) ||
  183.             ((theChar>='A') && (theChar<='Z')) ||
  184.             ((theChar>='0') && (theChar<='9')) ||
  185.             (theChar=='-') || (theChar=='_')))
  186.     {
  187.         theReferenceName[++theReferenceName[0]]=theChar;
  188.         theChar=GetTheCharacter(&dummyPosition);
  189.     }
  190.     
  191.     RememberCharacter(theChar);
  192.     
  193.     if (theReferenceName[0]==0x00)
  194.         return kNoReferenceName;
  195.     
  196.     *endPosition=dummyPosition;
  197.     return kNoError;
  198. }
  199.  
  200. static    enum ErrorType GetReferenceID(Str255 theReferenceName, short *refNum, short *numOptions)
  201. {
  202.     Handle            theResHandle;
  203.     Str255            name;
  204.     ResType            theType;
  205.     
  206.     SetResLoad(TRUE);
  207.     theResHandle=Get1NamedResource('STR#', theReferenceName);
  208.     if (theResHandle==0L)
  209.         return kBadReference;
  210.     
  211.     *numOptions=**((short**)theResHandle);
  212.     GetResInfo(theResHandle, refNum, &theType, name);
  213.     ReleaseResource(theResHandle);
  214.     
  215.     return kNoError;
  216. }
  217.  
  218. static    enum ErrorType InstantiateReference(Str255 theText, short refNum, short numOptions)
  219. {
  220.     GetIndString(theText, refNum, 1+((Random()&0x7fff)%numOptions));
  221.     return kNoError;
  222. }
  223.  
  224. static    enum ErrorType ReplaceTheText(short start, short end, Str255 theStr)
  225. {
  226.     long            textLength;
  227.     unsigned char    dummy;
  228.     short            dummyPos;
  229.     long            dummyLong;
  230.     
  231.     TESetSelect(start, end, gTheTEHandle);
  232.     TEDelete(gTheTEHandle);
  233.     textLength=theStr[0];
  234.     if (textLength>0)
  235.         TEInsert(&theStr[1], textLength, gTheTEHandle);
  236.     TESelView(gTheTEHandle);
  237.     SetWindowIsModified(gTheWindow, TRUE);
  238.     AdjustVScrollBar(GetWindowVScrollBar(gTheWindow), gTheTEHandle);
  239.     gRememberedCharValid=FALSE;
  240.     gTheTELength=(**gTheTEHandle).teLength;
  241.     gTheTEPosition=start-1;
  242.     if (gTheTEPosition<0)
  243.         gTheTEPosition=0;
  244.     else
  245.     {
  246.         dummy=GetTheCharacter(&dummyPos);
  247.         if (dummy=='#')
  248.             RememberCharacter(dummy);
  249.     }
  250.     
  251.     if (!DealWithOtherPeople())
  252.         return kUserCancelled;
  253.     if (!gInProgress)
  254.         return kUserCancelled;
  255.     if (!IndWindowExistsQQ(gTheWindowIndex))
  256.         return kUserCancelled;
  257.     
  258.     Delay(gSpeedDelay, &dummyLong);
  259.     
  260.     return kNoError;
  261. }
  262.  
  263. static    enum ErrorType GetChoiceText(Str255 theText, short start, short *end, Boolean chooseFirst)
  264. {
  265.     short            level;
  266.     unsigned char    theChar;
  267.     short            endOfFirstChoice;
  268.     short            thePosition;
  269.     
  270.     level=1;
  271.     theText[0]=0x00;
  272.     theChar=GetTheCharacter(&thePosition);
  273.     endOfFirstChoice=-1;
  274.     while (theChar!=0xFF)
  275.     {
  276.         if ((chooseFirst && (endOfFirstChoice==-1)) ||
  277.             (!chooseFirst && (endOfFirstChoice!=-1)))
  278.         {
  279.             theText[++theText[0]]=theChar;
  280.         }
  281.         
  282.         switch (theChar)
  283.         {
  284.             case '[':
  285.                 level++;
  286.                 break;
  287.             case ']':
  288.                 level--;
  289.                 if (level==0)
  290.                 {
  291.                     if (endOfFirstChoice==-1)
  292.                         return kBadChoiceFormat;
  293.                     *end=thePosition+1;
  294.                     theText[0]--;
  295.                     return kNoError;
  296.                 }
  297.                 break;
  298.             case '|':
  299.                 if (level==1)
  300.                 {
  301.                     if (endOfFirstChoice==-1)
  302.                         endOfFirstChoice=thePosition;
  303.                     else
  304.                         return kBadChoiceFormat;
  305.                 }
  306.                 break;
  307.         }
  308.         
  309.         theChar=GetTheCharacter(&thePosition);
  310.     }
  311.     
  312.     return kBadChoiceFormat;
  313. }
  314.  
  315. static    enum ErrorType GetOptionalText(Str255 theText, short start, short *end, Boolean useIt)
  316. {
  317.     short            level;
  318.     unsigned char    theChar;
  319.     short            thePosition;
  320.     
  321.     level=1;
  322.     theText[0]=0x00;
  323.     theChar=GetTheCharacter(&thePosition);
  324.     while (theChar!=0xFF)
  325.     {
  326.         if (useIt)
  327.         {
  328.             theText[++theText[0]]=theChar;
  329.         }
  330.         
  331.         switch (theChar)
  332.         {
  333.             case '<':
  334.                 level++;
  335.                 break;
  336.             case '>':
  337.                 level--;
  338.                 if (level==0)
  339.                 {
  340.                     *end=thePosition+1;
  341.                     if (useIt)
  342.                         theText[0]--;
  343.                     return kNoError;
  344.                 }
  345.                 break;
  346.         }
  347.         
  348.         theChar=GetTheCharacter(&thePosition);
  349.     }
  350.     
  351.     return kBadOptionalFormat;
  352. }
  353.